package club.mzwh.security.service.impl;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;

import club.mzwh.common.util.HttpUtil;
import club.mzwh.common.util.StringUtil;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

public class FilterSecurityInterceptorImpl extends AbstractSecurityInterceptor
		implements Filter {
	// 与applicationContext-security.xml里的myFilter的属性securityMetadataSource对应，
	// 其他的两个组件，已经在AbstractSecurityInterceptor定义
	private FilterInvocationSecurityMetadataSource securityMetadataSource;
	private static final String FILTER_APPLIED = "__spring_security_filterSecurityInterceptor_filterApplied";
	private boolean observeOncePerRequest = true;

	@Override
	public SecurityMetadataSource obtainSecurityMetadataSource() {
		return this.securityMetadataSource;
	}

	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		FilterInvocation fi = new FilterInvocation(request, response, chain);
		System.out.println("Call FilterSecurityInterceptorImpl filter==="
				+ request.getRequestURI());

		String code = request.getParameter("code");
		System.out.println("code=====" + code);
		if (StringUtil.isNotNullOrEmpty(code)) {
			String tokenurl = "http://localhost:8080/oauth/token";
			String tokenParam = "client_id=TestSSO&grant_type=authorization_code&redirect_uri=http://localhost:8088/sso/auth/nw&client_secret=user123&code="
					+ code;
			String ret;
			try {
				ret = HttpUtil.sendGet(tokenurl, tokenParam);
				System.out.println("start==" + ret);
				// String token = request.getHeader("json-token");
				// System.out.println("token==="+token);

				JSONObject jsonObject = JSON.parseObject(ret);
				String accessToken =  jsonObject.getString("access_token");
				if (StringUtil.isNotNullOrEmpty(accessToken)) {
					String aa = HttpUtil.sendGet("http://localhost:8080/user/token/"+accessToken, "");
					System.out.println("aa=="+aa);
					JSONObject udm = JSON.parseObject(aa);
					System.out.println("udm="+udm);
					System.out.println(udm.getJSONArray("authorities"));
	
					JSONArray authoritiesArray = udm.getJSONArray("authorities");
					String[] authorities = new String[authoritiesArray.size()];
					for (int i = 0; i < authoritiesArray.size(); i++) {
						authorities[i] = authoritiesArray.getString(i);
					}
	
					// 将用户信息和权限填充 到用户身份token对象中
					UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
							udm, null,
							AuthorityUtils.createAuthorityList(authorities));
					authenticationToken
							.setDetails(new WebAuthenticationDetailsSource()
									.buildDetails(request));
					// 将authenticationToken填充到安全上下文
					SecurityContextHolder.getContext().setAuthentication(
							authenticationToken);
					System.out.println("ret===" + ret);
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		if ("anonymousUser".equals(SecurityContextHolder.getContext()
				.getAuthentication().getName())
				&& !(noCheck(((FilterInvocation) fi).getRequestUrl()))) {
			response.sendRedirect(request.getContextPath() + "/view/login.jsp");
		} else {
			invoke(fi);
		}
	}

	public void invoke(FilterInvocation fi) throws IOException,
			ServletException {
		if ((fi.getRequest() != null)
				&& (fi.getRequest().getAttribute(FILTER_APPLIED) != null)
				&& observeOncePerRequest) {
			fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
		} else {

			if (fi.getRequest() != null) {
				fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
			}
			InterceptorStatusToken token = super.beforeInvocation(fi);
			try {
				fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
			} finally {
				super.finallyInvocation(token);
			}
			super.afterInvocation(token, null);
		}
	}

	public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
		return securityMetadataSource;
	}

	public void setSecurityMetadataSource(
			FilterInvocationSecurityMetadataSource securityMetadataSource) {
		this.securityMetadataSource = securityMetadataSource;
	}

	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
	}

	public void destroy() {
		// TODO Auto-generated method stub

	}

	@Override
	public Class<? extends Object> getSecureObjectClass() {
		// 下面的MyAccessDecisionManager的supports方面必须放回true,否则会提醒类型错误
		return FilterInvocation.class;
	}

	private boolean noCheck(String url) {
		String str = "login.jsp||login";
		return str.contains(url) || url.contains("/image/rand");
	}
}